package top.heue.utils.lifecycle.base

import androidx.annotation.Keep
import androidx.databinding.Observable
import androidx.databinding.PropertyChangeRegistry
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

open class BaseModel : ViewModel(), Observable {
    /*DataBinding数据更新触发实现*/
    private val callbacks: PropertyChangeRegistry by lazy { PropertyChangeRegistry() }

    override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
        callbacks.add(callback)
    }

    override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
        callbacks.remove(callback)
    }

    fun notifyChange() {
        callbacks.notifyCallbacks(this, 0, null)
    }

    fun notifyPropertyChanged(fieldId: Int) {
        callbacks.notifyCallbacks(this, fieldId, null)
    }
}


/*MVI Support*/
/** MVI 页面事件管理基类*/
@Keep
interface IUiIntent

/** MVI 页面持久状态管理基类*/
@Keep
interface IUiState

/** MVI 页面临时状态管理基类*/
@Keep
interface IUiEffect

/** 实现MVI支持的Model*/
abstract class BaseMVIModel<UiIntent : IUiIntent, UiState : IUiState, UiEffect : IUiEffect> :
    BaseModel() {
    /**页面状态*/
    private val _uiStateFlow by lazy { MutableStateFlow(initUiState) }

    /**页面状态*/
    val uiStateFlow: StateFlow<UiState> by lazy { _uiStateFlow }

    /**一次性事件，无需更新*/
    private val _effectFlow by lazy { MutableSharedFlow<UiEffect>() }

    /**一次性事件，无需更新*/
    val uiEffectFlow: SharedFlow<UiEffect> by lazy { _effectFlow.asSharedFlow() }

    /**页面事件的 Channel 分发*/
    private val _uiIntentFlow by lazy { Channel<UiIntent>(Channel.UNLIMITED) }

    /** 当前页面持久状态*/
    val currentUiState: UiState get() = _uiStateFlow.value

    init {
        // 这里是通过Channel的方式自动分发的。
        viewModelScope.launch {
            //收集意图 （观察者模式改变之后就自动更新）用于协程通信的，所以需要在协程中调用
            _uiIntentFlow.consumeAsFlow().collect { intent ->
                onIntent(intent)
            }
        }
    }

    /**更新页面状态*/
    fun sendUiState(reducer: UiState.() -> UiState) {
        _uiStateFlow.update { reducer(_uiStateFlow.value) }
    }

    /**触发一次性状态*/
    fun sendUiEffect(builder: suspend () -> UiEffect?) = viewModelScope.launch {
        builder()?.let { _effectFlow.emit(it) }
    }

    /**触发一次性状态*/
    suspend fun sendUiEffect(effect: UiEffect) = _effectFlow.emit(effect)

    /**状态分发简化*/
    fun onState(viewLifecycleOwner: LifecycleOwner, block: UiState.() -> Unit) {
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                uiStateFlow.collect(block)
            }
        }
    }

    /**状态分发简化，默认不触发状态不改变的重复事件*/
    fun <R> onState(
        viewLifecycleOwner: LifecycleOwner,
        map: suspend UiState.() -> (R),
        isRepeat: Boolean = false,
        block: R.() -> Unit
    ) {
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                var flow = uiStateFlow.map(map)
                if (!isRepeat) flow = flow.distinctUntilChanged()
                flow.collect(block)
            }
        }
    }

    /**一次性状态分发简化，注意需在状态至少为STARTED才会触发*/
    fun onEffect(viewLifecycleOwner: LifecycleOwner, block: UiEffect.() -> Unit) {
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                uiEffectFlow.collect(block)
            }
        }
    }

    /**
     * 一次性状态分发简化，不知道有没有用到的地方先实现着，默认可产生重复事件
     * 注意需在状态至少为STARTED才会触发，基本用不到
     */
    fun <R> onEffect(
        viewLifecycleOwner: LifecycleOwner,
        map: suspend UiEffect.() -> (R),
        isRepeat: Boolean = true,
        block: R.() -> Unit
    ) {
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
                var flow = uiEffectFlow.map(map)
                if (!isRepeat) flow = flow.distinctUntilChanged()
                flow.collect(block)
            }
        }
    }

    /**触发页面事件
     * DataBinding调用示例：android:onClick="@{(view)->model.sendUiIntent(UiIntent.Touch.INSTANCE)}"
     */
    fun sendUiIntent(uiIntent: UiIntent) {
        viewModelScope.launch {
            _uiIntentFlow.send(uiIntent)
        }
    }

    /**页面初始UiState实例化*/
    protected abstract val initUiState: UiState

    /**页面UiIntent事件触发处理*/
    protected abstract fun onIntent(intent: UiIntent)
}